//
//  Bounce.m
//  PezMonkey
//
//  Created by Spence DiNicolantonio on 12/22/09.
//  Copyright 2009 Necrosoft. All rights reserved.
//

#import "Bounce.h"

#define kBoxCount 10


@implementation Bounce

@synthesize staticBody;

- (NSString *)demoName {
	return @"Bounce";
}

- (void)start {
	// create space
	self.space = [PMSpace space];
	[space setSubSteps:3];
	[space setIterations:10];
	[space setActiveHashSize:1000 cellDimension:30];
	
	// add screen boundary
	[self addScreenBoundary];
	
	// add boxes
	for (int i=0; i<kBoxCount; i++)
		[self addBox];
	
	
	// create segment body
	PMBody *segmentBody = [PMBody bodyWithMass:100 
										moment:10000];
	[space addBody:segmentBody];
	
	// create segment shape
	PMFloat length = 150;
	PMFloat width = 10;
	PMShape *segmentShape = [PMSegmentShape segmentShapeWithBody:segmentBody 
														   start:PMVectMake(-length / 2, 0) 
															 end:PMVectMake(length / 2, 0)
														   width:width];
	[segmentShape setFriction:1.0];
	[segmentShape setElasticity:1.0];
	[space addShape:segmentShape];
	
	// stick the segment to the screen by attaching a pivot joint to the segment 
	// and a static body.
	self.staticBody = [PMBody staticBody];
	PMConstraint *joint = [PMPivotJoint pivotJointWithBodyA:segmentBody 
													  bodyB:staticBody];
	[space addConstraint:joint];	
}

/**
 * Creates and segment shapes to demo space to make a boundary along the edges of
 * the screen.
 */
- (void)addScreenBoundary {
	// make sure static body has been initialized
	if (!staticBody)
		self.staticBody = [PMBody staticBody];
	
	// create temp shape
	PMShape *shape;
	
	// define boundary segment width 
	// (needs to be thick to avoid penetration at high velocities)
	PMFloat width = 30;
	
	// create left screen boundary
	shape = [PMSegmentShape segmentShapeWithBody:staticBody
										   start:PMVectMake(-320 - width/2, -240)
											 end:PMVectMake(-320 - width/2, 240)
										   width:width];
	[shape setElasticity:1.0];
	[shape setFriction:1.0];
	[shape setLayers:PMLayerMaskNotGrabbable];
	[space addStaticShape:shape];
	
	// create right screen boundary
	shape = [PMSegmentShape segmentShapeWithBody:staticBody
										   start:PMVectMake(320 + width/2, -240) 
											 end:PMVectMake(320 + width/2, 240)
										   width:width];
	[shape setElasticity:1.0];
	[shape setFriction:1.0];
	[shape setLayers:PMLayerMaskNotGrabbable];
	[space addStaticShape:shape];
	
	// create bottom screen boundary
	shape = [PMSegmentShape segmentShapeWithBody:staticBody
										   start:PMVectMake(-320, -240 - width/2) 
											 end:PMVectMake(320, -240 - width/2)
										   width:width];
	[shape setElasticity:1.0];
	[shape setFriction:1.0];
	[shape setLayers:PMLayerMaskNotGrabbable];
	[space addStaticShape:shape];
	
	// create top screen boundary
	shape = [PMSegmentShape segmentShapeWithBody:staticBody
										   start:PMVectMake(-320, 240 + width/2) 
											 end:PMVectMake(320, 240 + width/2)
										   width:width];
	[shape setElasticity:1.0];
	[shape setFriction:1.0];
	[shape setLayers:PMLayerMaskNotGrabbable];
	[space addStaticShape:shape];
}

/**
 * Creates and adds a box to the demo space in a random position with random
 * velocity.
 */
- (void)addBox {
	// define box attributes
	PMFloat width = 10.0;
	PMFloat mass = 1.0;
	
	// define box vertices
	NSUInteger vertCount = 4;
	PMVect verts[] = {
		PMVectMake(-width,-width),
		PMVectMake(-width, width),
		PMVectMake( width, width),
		PMVectMake( width,-width),
	};
	
	// calculate box moment
	PMFloat moment = PMMomentForPolygon(mass, verts, vertCount, PMVectZero);
	
	// create box body
	PMBody *body = [PMBody bodyWithMass:mass moment:moment];
	
	// set random box position
	PMFloat xPos = (PMFloatRandom() * (640 - width / 2)) - (320 - width / 2);
	PMFloat yPos = (PMFloatRandom() * (480 - width / 2)) - (240 - width / 2);
	[body setPosition:PMVectMake(xPos, yPos)];
	
	// set random box velocity
	PMFloat xVel = (2*PMFloatRandom() - 1) * 250;
	PMFloat yVel = (2*PMFloatRandom() - 1) * 250;
	[body setVelocity:PMVectMake(xVel, yVel)];
	 
	// add box body to space
	[space addBody:body];
	
	// create box shape
	PMShape *shape = [PMPolygonShape polygonShapeWithBody:body 
												 vertices:verts 
											  vertCount:vertCount];
	[shape setFriction:0.0];
	[shape setElasticity:1.0];
	[space addShape:shape];
}


#pragma mark -
#pragma mark Dealloc

- (void)dealloc {
	[staticBody release];
	[super dealloc];
}

@end
